package com.leetroll.media.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.JsonObject;
import com.leetroll.api.service.FileService;
import com.leetroll.api.service.ItemService;
import com.leetroll.common.bean.ApiResponse;
import com.leetroll.common.entity.Item;
import com.leetroll.common.enums.EFileType;
import com.leetroll.common.utils.AliyunOSSUtil;
import com.leetroll.media.service.CleanService;
import com.leetroll.media.utils.ImgDealUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.imageio.ImageIO;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;
import java.io.File;

/**
 * @Author qdy
 * @Date 2024/3/23 15:14
 * 3d模型文件整理上传阿里云服务器处理
 */
@RestController
@RequestMapping("/file")
@Slf4j
public class FileDealController {
    private static final ArrayList<String> errorResult = new ArrayList<>();
    private final ItemService itemService;
    private final FileService fileService;
    private final CleanService cleanService;

    @Autowired
    public FileDealController(ItemService itemService,FileService fileService,CleanService cleanService) {
        this.fileService = fileService;
        this.itemService = itemService;
        this.cleanService = cleanService;
    }

    @PostMapping("/clean")
    public ApiResponse<String> cleanAliyunItems(){
        QueryWrapper<Item> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("author", "qdy");
        List<Item> items = itemService.list(queryWrapper);
        cleanService.clean(items);
        return ApiResponse.OK("成功！");
    }

    @PostMapping("/dealDataUpdate")
    public ApiResponse<String> dealLocal3dModelFile() throws IOException {
        String inputDir="E:\\leetroll-3d-item";
        File inputFile = new File(inputDir);
        // 1。读取每一个压缩包， 解压缩找出主图，预览图, 原本的压缩包作为资源附件
        Map<String, List<Object>> resultMap = loadFileFindAllData(inputFile);
        Map<String, File> attachFileMap = loadAttachmentFile();

        if (resultMap == null || resultMap.isEmpty()) {
            return ApiResponse.FAIL("No files found.");
        }

        System.out.println("总共加载资源个数"+resultMap.size());
        long startTime = System.currentTimeMillis();

        // 3.上传文件(主图 预览图 附件) 到阿里云bucket
        int index=1;
        for (Map.Entry<String, List<Object>> map : resultMap.entrySet()){
            String fileName = map.getKey();
            List<Object> fileList = map.getValue();
            // 2.读取每一个压缩包，新建item （对应item表），插入数据库
            try {
                Item item = createItem(fileName);
                if (item != null) {
                    uploadFiles(item.getId(), fileList,fileName,attachFileMap);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            System.out.println("获取itemid-->"+"耗时"+(System.currentTimeMillis() - startTime)+"-->第"+index+"个");
            startTime = System.currentTimeMillis();
            index++;
        }

        JsonObject jsonObject = new JsonObject();
        String errorData = errorResult.isEmpty() ? null : String.join(",", errorResult);
        jsonObject.addProperty("errorData", errorData);
        jsonObject.addProperty("success", "成功");
        return ApiResponse.OK(jsonObject.toString());
    }

    public void uploadFiles(Long itemId,List<Object> list,String fileName,Map<String, File> attachFileMap) throws IOException {
        String mainPath="item/"+itemId+"/main/";
        String previewPath="item/"+itemId+"/preview/";
        String attachmentPath="item/"+itemId+"/attachment/";

        //获取对应的文件
        File mainFile = (File) list.get(0);
        List<File> previewFile = (List<File>) list.get(1);
        File attachmentFile = findattachmentFile(fileName,attachFileMap);

        // 上传主图
        uploadAndSaveFile(itemId, mainFile, mainPath, EFileType.MAIN);
        // 上传预览图
        for(File file:previewFile){
            uploadAndSaveFile(itemId, file, previewPath, EFileType.PREVIEW);
        }
        // 上传附件
        assert attachmentFile != null;
        uploadAndSaveFile(itemId, attachmentFile, attachmentPath, EFileType.ATTACHMENT);
    }

    public void uploadAndSaveFile(Long itemId, File file, String path,EFileType fileType) throws IOException {
        String filePath = path + file.getName();
        String name=file.getName().split("\\.")[0];
        String suffix=file.getName().split("\\.")[1];

        AliyunOSSUtil.upload(filePath, Files.newInputStream(file.toPath()));
        fileService.saveFile(itemId, path, name, suffix, "leetroll-private", fileType.getType(), file.length(), suffix);
    }

    public Item createItem(String fileName) {
        Boolean isSuccess = itemService.saveItem(fileName, fileName);
        if (isSuccess) {
            QueryWrapper<Item> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("name", fileName);
            queryWrapper.orderByDesc("create_time");
            queryWrapper.last("limit 1");
            return itemService.getOne(queryWrapper);
        }
        return null;
    }
    /**
     * @Author qdy
     * @Description  查找压缩包文件
     * @Date 11:36 2024/3/28
     **/
    public static File findattachmentFile(String fileName,Map<String, File> attachFileMap){
        return attachFileMap.get(fileName);
    }

    public static Map<String, File> loadAttachmentFile(){
        HashMap<String, File> result = new HashMap<>();
        String dealDir="E:\\leetroll-3d-attach";
        File dirFile = new File(dealDir);
        File[] allFiles = dirFile.listFiles();
        assert allFiles != null;
        for(File file:allFiles){
            String name = file.getName();
            name =name.split("\\.")[0];
            result.put(name,file);
        }
        return result;
    }

    /**
     * @Author qdy
     * @Description  读取每一个压缩包， 解压缩找出主图，预览图, 原本的压缩包作为资源附件
     * @Date 16:04 2024/3/23
     * @Param [file]
     **/
    public static Map<String, List<Object>> loadFileFindAllData(File file) throws IOException {
        //最终返回结果【key（文件夹名称）--value（文件夹内容,主要包含主图和预览图）】
        HashMap<String, List<Object>> map = new HashMap<>();
        // 要检查的文件夹名称
        String checkFileName = "_RenderPics";
        if (file == null) {
            return null;
        }
        //获取指定目录下所有的文件
        File[] topLeverAllFiles = file.listFiles();
        for (int i = 0; i < Objects.requireNonNull(topLeverAllFiles).length; i++) {
            File topLeverAllFile = topLeverAllFiles[i];
            String key = topLeverAllFile.getName();
            //最终子目录
            File[] secondLeverAllFiles = topLeverAllFile.listFiles();
            //最终子目录，因为有的有一层有的有多层，一层的需要继续往里面找，多层的表示已经是最里层
            File[] childFiles;
            assert secondLeverAllFiles != null;
            if(secondLeverAllFiles.length==1){
                childFiles = secondLeverAllFiles[0].listFiles();
            }else{
                childFiles=secondLeverAllFiles;
            }
            //是否存在预览图目录
            boolean isExistRenderPics=false;
            if(childFiles==null){
                errorResult.add(key);
                continue;
            }
            for(File f:childFiles){
                if (f.isDirectory() && f.getName().equals(checkFileName)) {
                    isExistRenderPics=true;
                }
            }
            //根目录当前项目名称
            String topDirName = topLeverAllFile.getName();
            //先判断一下有没有和文件名称相同的图片作为主图，如果没有就使用contain包含查询
            boolean isExitMainImg=false;
            for (File childFile : childFiles) {
                if (!isExistRenderPics) {
                    String curFile = childFile.getName();
                    String newImgName = curFile.split("\\.")[0];
                    boolean isImg = curFile.endsWith("png") || curFile.endsWith("jpg") || curFile.endsWith("jpeg");
                    if (newImgName.equals(topDirName) && (isImg)) {
                        isExitMainImg = true;
                    }
                }
            }
            dealChildFiles(childFiles,isExistRenderPics,isExitMainImg,checkFileName,topDirName,key,map,errorResult);
        }
        return map;
    }

    /**
     * @Author qdy
     * @Description  处理子分录文件，进行水印处理
     * @Date 15:44 2024/4/3
     * @Param [childFiles, isExistRenderPics, isExitMainImg, checkFileName, topDirName, key, map, errorResult]
     **/
    public static void dealChildFiles(File[] childFiles, boolean isExistRenderPics,boolean isExitMainImg,
                                      String checkFileName, String topDirName,String key,Map<String, List<Object>> map,List<String> errorResult) throws IOException {
        ArrayList<Object> result = new ArrayList<>();
        //主图
        File mainImg = null;
        //预览图
        ArrayList<File> PreviewImg = new ArrayList<>();
        int size=1;

        for (File childFile : childFiles) {
            String outputPath = childFile.getParentFile().getAbsolutePath();
            String fileName = childFile.getName();
            boolean isImageFile = fileName.endsWith("png") || fileName.endsWith("jpg") || fileName.endsWith("jpeg");

            //有预览地址目录，直接找对应的目录文件预览图与主图
            if (isExistRenderPics) {
                if (childFile.isDirectory() && childFile.getName().equals(checkFileName)) {
                    File[] renderFiles = childFile.listFiles();
                    if (renderFiles != null) {
                        for (int i=0;i<renderFiles.length;i++) {
                            File renderFile=renderFiles[i];
                            String renderFileName = renderFile.getName();
                            isImageFile = renderFileName.endsWith("png") || renderFileName.endsWith("jpg") || renderFileName.endsWith("jpeg");
                            if (isImageFile) {
                                if(i==0) {
                                    mainImg = processImage(renderFile, outputPath);
                                }
                                processImage(renderFile, outputPath, "render" + size + ".png", PreviewImg);
                                size++;
                            }
                        }
                    }
                }
            } else {
                String curFileName = fileName.split("\\.")[0];
                boolean chooseImg = curFileName.contains(topDirName) || curFileName.contains("render") || curFileName.equals("R1") || curFileName.equals("R2") || curFileName.equals("R3");
                if (isImageFile) {
                    //如果不包含主图，随机找一张预览图作为主图
                    if(!isExitMainImg&&chooseImg){
                        // Process main image
                        mainImg=processImage(childFile, outputPath);
                    }else if (isExitMainImg&&curFileName.equals(topDirName)) {
                        // Process main image
                        mainImg=processImage(childFile, outputPath);
                    }
                    if (chooseImg) {
                        // Process other images
//                        processImage(childFile, outputPath, "main.png", mainImg);
                        processImage(childFile, outputPath, "render" + size + ".png", PreviewImg);
                        size++;
                    }
                }
            }
        }

        //没有主图表示可能是贴图不需要添加
        if(mainImg!=null) {
            result.add(mainImg);
            result.add(PreviewImg);
            map.put(key, result);
        }else{
            errorResult.add(topDirName);
        }
    }

    private static void processImage(File imageFile, String outputPath, String outputFileName, List<File> fileList) throws IOException {
        File watermarkImg = ImgDealUtil.getWatermark(ImageIO.read(imageFile));
        File resultImg = ImgDealUtil.manageWatermark(ImageIO.read(imageFile), ImageIO.read(watermarkImg), imageFile.getName(), outputPath + "\\" + outputFileName);
        if (outputFileName.equals("main.png")) {
            fileList.add(resultImg);
        } else {
            fileList.add(resultImg);
        }
    }

    private static File processImage(File imageFile, String outputPath) throws IOException {
        File watermarkImg = ImgDealUtil.getWatermark(ImageIO.read(imageFile));
        return ImgDealUtil.manageWatermark(ImageIO.read(imageFile), ImageIO.read(watermarkImg), imageFile.getName(), outputPath + "\\" + "main.png");
    }

    public static void main(String[] args) throws IOException {
        String dealDir="E:\\leetroll-3d-test";
        File dirFile = new File(dealDir);
        loadFileFindAllData(dirFile);
    }
}
